/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package objects;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import org.placelab.spotter.SpotterException;

/**
 *
 * @author Nam
 */
public class ScanningLocation implements Serializable
{
    private ArrayList<AccessPoint> m_APList = new ArrayList<AccessPoint>();
    private String locationName;
    public ScanningLocation()
    {

    }
    public ScanningLocation(String m_locationname)
    {
        this.locationName = m_locationname;
    }

    public ScanningLocation (ScanningLocation lc)
    {
        this.locationName = lc.locationName;
        this.m_APList = lc.m_APList;
    }

    public ArrayList<AccessPoint> startScanning() throws SpotterException
    {
        WifiManager m_wifiManager = new WifiManager();
        this.m_APList = m_wifiManager.startScanning();
        return this.m_APList;
    }

    public int writeScanningResultToFile()
    {
        try
        {
            FileOutputStream fos = new FileOutputStream(locationName);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            for(int i =0;i<m_APList.size();i++)
            {
                AccessPoint p = m_APList.get(i);
                oos.writeObject(p);
            }
            //close
            fos.close();
            oos.close();
            return 1;
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return -1;
        }
    }
    
    public double computeDistance(ScanningLocation lc)
    {

        int len = lc.m_APList.size();
        double distance = 0;
        double penalty = 0;
        for (int i = 0; i < len; i++)
        {
            int j;
            for (j=0; j<len; j++)
            {
                  //String t = lc.m_APList.get(i).getSSID();
                  //System.out.println(t);
                  if (lc.m_APList.get(i).getSSID().equalsIgnoreCase(this.m_APList.get(j).getSSID()))
                  {
                    distance = distance + (lc.m_APList.get(i).getRSSI() - this.m_APList.get(j).getRSSI())*(lc.m_APList.get(i).getRSSI() - this.m_APList.get(j).getRSSI());
                    break;
                  }
            }
            if (j == len)
                penalty = penalty + Math.pow(0 - lc.m_APList.get(i).getRSSI(), 0.5);
        }
        return penalty + Math.pow(distance, 0.5);
    }
    public double computeDistanceSubset(ScanningLocation lc)
    {
        ArrayList<Integer> indexList = new ArrayList<Integer>();
        //ArrayList<Integer> penaltyList = new ArrayList<Integer>();
        int lenLc = lc.m_APList.size();
        int lenThis = this.m_APList.size();
        double distance = 0;
        double penalty = 0;
        for (int i = 0; i < lenThis; i++)
        {
            int j;
            for (j=0; j<lenLc; j++)
            {
                  //String t = lc.m_APList.get(i).getSSID();
                  //System.out.println(t);
                  if (lc.m_APList.get(j).getSSID().equalsIgnoreCase(this.m_APList.get(i).getSSID()))
                  {
                    distance = distance + (lc.m_APList.get(j).getRSSI() - this.m_APList.get(i).getRSSI())*(lc.m_APList.get(j).getRSSI() - this.m_APList.get(i).getRSSI());
                    indexList.add(new Integer(i));
                    break;
                  }

            }
            if (j == lenLc)
            {

                penalty = penalty + Math.pow(0-this.m_APList.get(i).getRSSI(), 0.5);
            }
        }
        if (indexList.size() == lenLc)
            return penalty + Math.pow(distance, 0.5);
        return 10000;
    }

    
    
    public int writeScanningResultToFile(File m_file)
    {
        try
        {
            FileOutputStream fos = new FileOutputStream(m_file,false);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            for(int i =0;i<m_APList.size();i++)
            {
                AccessPoint p = m_APList.get(i);
                oos.writeObject(p);
            }
            //close
            fos.close();
            oos.close();
            return 1;
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return -1;
        }
    }

    public int createBlankFile(File m_file)
    {
        try
        {
            FileOutputStream fos = new FileOutputStream(m_file);
            //close
            fos.close();
            return 1;
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return -1;
        }
    }

    public ScanningLocation readScanningResultFromFile(String fileName)
    {
        ScanningLocation location = new ScanningLocation(fileName);
        ArrayList<AccessPoint> _apList= new ArrayList<AccessPoint>();
        AccessPoint p = null;
        try
        {
            FileInputStream fis = new FileInputStream(fileName);
            ObjectInputStream ois = new ObjectInputStream(fis);

            while(ois.available()>-1)
            {
                p = (AccessPoint)ois.readObject();
                if(p == null)
                    break;
                _apList.add(p);
            }
            fis.close();
            ois.close();
        }
        catch(Exception e)
        {
            System.out.println("Finish Reading");
        }
        location.setM_APList(_apList);
        return location;
    }

    //file object
    public ScanningLocation readScanningResultFromFile(File m_file)
    {
        ScanningLocation location = new ScanningLocation(m_file.getName());
        ArrayList<AccessPoint> _apList= new ArrayList<AccessPoint>();
        AccessPoint p = null;
        try
        {
            FileInputStream fis = new FileInputStream(m_file);
            ObjectInputStream ois = new ObjectInputStream(fis);

            while(ois.available()>-1)
            {
                p = (AccessPoint)ois.readObject();
                if(p == null)
                    break;
                _apList.add(p);
            }
            fis.close();
            ois.close();
        }
        catch(Exception e)
        {
            System.out.println("Finish Reading");
        }
        location.setM_APList(_apList);
        return location;
    }

    public void printResult()
    {
        System.out.println(m_APList.size() + " APs were seen at Location: "+this.locationName+"\n");
        if(m_APList.size()>0)
        {
            System.out.println(pad("MAC Address", 20) + pad("SSID", 30)+ pad("RSSI", 10));
            for (int i = 0; i < m_APList.size(); i++)
            {
                AccessPoint m_accessPoint = (AccessPoint) m_APList.get(i);
                System.out.println(pad(m_accessPoint.getMacAddress(), 20)+ pad(m_accessPoint.getSSID(), 30) + pad("" + m_accessPoint.getRSSI(), 10));
            }
        }
    }

    public String getResult()
    {
        String result = "";
        result+=m_APList.size() + " APs were seen at Location: "+this.locationName+"\n";
        if(m_APList.size()>0)
        {
            result+=pad("MAC Address", 20) + pad("SSID", 30)+ pad("RSSI", 10) +"\n";
            for (int i = 0; i < m_APList.size(); i++)
            {
                AccessPoint m_accessPoint = (AccessPoint) m_APList.get(i);
                result+=pad(m_accessPoint.getMacAddress(), 20)+ pad(m_accessPoint.getSSID(), 30) + pad("" + m_accessPoint.getRSSI(), 10) + "\n";
            }
        }
        return result;
    }

    public static String pad(String str, int len)
    {
        StringBuffer sb = new StringBuffer(str);
        for (int i=str.length(); i < len; i++)
        {
            sb.append(" ");
        }
        return sb.toString();
    }



    /**
     * @return the m_APList
     */
    public ArrayList<AccessPoint> getM_APList() {
        return m_APList;
    }

    /**
     * @param m_APList the m_APList to set
     */
    public void setM_APList(ArrayList<AccessPoint> m_APList) {
        this.m_APList = m_APList;
    }

    /**
     * @return the locationName
     */
    public String getLocationName() {
        return locationName;
    }

    /**
     * @param locationName the locationName to set
     */
    public void setLocationName(String locationName) {
        this.locationName = locationName;
    }

}
